﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Text;
using System.Windows.Forms;
using LumenWorks.Framework.IO.Csv;
using SdmxMl.Structure;
using SdmxMl.Manager;
using System.Xml;

namespace SdmxMl.Data
{
    public class EsurveyDataImport
    {
        const string KEY_RESPONDENT_DATA = "RespondentData";
        const string KEY_RESPONDENT = "Respondent";
        const string KEY_RESPONDENT_ID = "respondentID";
        const string KEY_SUBQUEST_ID = "subID";
        const string KEY_IMPORT_DATA = "ImportRespData";
        const string CURSOR_TAG = "Cursor";
        const string CURSOR_ROW_TAG = "Row";

        /// <summary>Provides meta information associated on each column of CSV</summary>
        private CsvDataHeader metaDataHeader;

        /// <summary>Provides meta information associated on Respondent Id</summary>
        private CsvMetaHeaderCol respondentCol;
        private int respondentColIndex;

        private List<string> listGlobal;

        private List<RepeaterRow> listRepeater;
        private RepeaterRow globalVar;

        public EsurveyDataImport(CsvDataHeader metaHeader, KeyFamilyType kfDsd)
        {
            metaDataHeader = metaHeader;

            // Check that respondent ID is designed
            if ((respondentCol = GetRespondentCol(ref respondentColIndex)) == null)
            {
                throw new ArgumentException("Invalid, no dimension specifies respondentID");
            }

            listGlobal = new List<string>();
            foreach (KeyValuePair<int, CsvMetaHeaderCol> pair in metaDataHeader.DicoHeadCol)
                listGlobal.Add(pair.Value.Concept.Id);

            listRepeater = new List<RepeaterRow>();
            foreach (GroupType gtl in kfDsd.GroupList)
            {
                listRepeater.Add(new RepeaterRow(gtl.Id, gtl.DimensionRefList));
                foreach (string s in gtl.DimensionRefList)
                    listGlobal.Remove(s);
            }

            globalVar = new RepeaterRow("global var", listGlobal);


        }

        private CsvMetaHeaderCol GetRespondentCol(ref int respondentColIndex)
        {
            foreach (KeyValuePair<int, CsvMetaHeaderCol> pair in metaDataHeader.DicoHeadCol)
            {
                if (pair.Value.BaseVar.Id == KEY_RESPONDENT_ID)
                {
                    respondentColIndex = pair.Key;
                    return pair.Value;
                }
            }
            return null;
        }

        public void produceExport(CachedCsvReader csvReader, string esXmpPath)
        {
            string respondent = null;
            using (XmlTextWriter xw = new XmlTextWriter(esXmpPath, System.Text.Encoding.UTF8))
            {
                xw.Formatting = Formatting.Indented;
                xw.WriteStartDocument();
                xw.WriteStartElement(KEY_RESPONDENT_DATA);

                while (csvReader.ReadNextRecord())
                {
                    string currentRespondent = csvReader[respondentColIndex];
                    bool newRow = currentRespondent != respondent;
                    if (newRow)
                    {
                        if (respondent != null)
                            WriteRespondent(xw, respondent);
                        respondent = currentRespondent;
                    }

                    foreach (KeyValuePair<int, CsvMetaHeaderCol> pair in metaDataHeader.DicoHeadCol)
                    {
                        string val = csvReader[pair.Key];
                        if (newRow)
                        {
                            globalVar.AddValue(pair.Value.Concept.Id, val);
                        }
                        foreach (RepeaterRow rpt in listRepeater)
                        {
                            rpt.AddValue(pair.Value.Concept.Id, val);
                        }
                    }
                }
                WriteRespondent(xw, respondent);
                xw.WriteEndElement();
                xw.WriteEndDocument();
                xw.Flush();
            }
        }

        private void WriteRespondent(XmlTextWriter xw, string respondent)
        {
            xw.WriteStartElement(KEY_RESPONDENT);
            xw.WriteElementString(KEY_RESPONDENT_ID, respondent);
            xw.WriteElementString(KEY_SUBQUEST_ID, string.Empty);

            xw.WriteStartElement(KEY_IMPORT_DATA);

            // Globals
            foreach (KeyValuePair<string, List<string>> kvp in globalVar.dicoColValue)
            {
                if (kvp.Value[0].Length > 0)
                    xw.WriteElementString(AdjustVarName(kvp.Key), kvp.Value[0]);
            }

            // Repeater
            foreach (RepeaterRow rpt in listRepeater)
            {
                xw.WriteStartElement(CURSOR_TAG);
                xw.WriteAttributeString("id", rpt.Id);

                for (int row = 0; row < rpt.Count; row++)
                {
                    if (rpt.IsEmptyRow(row) == false)
                    {
                        xw.WriteStartElement(CURSOR_ROW_TAG);
                        foreach (KeyValuePair<string, List<string>> kvp in rpt.dicoColValue)
                        {
                            if (kvp.Value[row].Length > 0)
                                xw.WriteElementString(AdjustVarName(kvp.Key), kvp.Value[row]);
                        }
                        xw.WriteEndElement();
                    }
                }
                xw.WriteEndElement();
            }
            xw.WriteEndElement();
            xw.WriteEndElement();
        }

        private void WriteRepeaters(XmlTextWriter xw, string respondent)
        {
        }


        private string AdjustVarName(string name)
        {
            return name.Replace("_", "x");
        }
    }


    public class RepeaterRow
    {
        public string Id { get; private set; }
        public int Count { get; private set; }

        private string targetCountKey;

        public Dictionary<string, List<string>> dicoColValue;

        public RepeaterRow(string id, List<string> cols)
        {
            this.Id = id;
            dicoColValue = new Dictionary<string, List<string>>();
            foreach (string col in cols)
                dicoColValue.Add(col, new List<string>());
            Count = 0;
            targetCountKey = cols[0];
        }

        public void Clear()
        {
            foreach (List<string> list in dicoColValue.Values)
                list.Clear();
            Count = 0;
        }

        public bool IsEmptyRow(int index)
        {
            foreach (List<string> list in dicoColValue.Values)
                if (list[index] != null && list[index].Length > 0)
                    return false;
            return true;
        }

        public void AddValue(string colId, string val)
        {
            if (dicoColValue.ContainsKey(colId))
            {
                dicoColValue[colId].Add(val);
                if (colId == targetCountKey)
                    Count++;
            }
        }

    }
}
